#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_lpm.h>
#include <rte_log.h>
#include <rte_mbuf.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define RTE_LOG_LEVEL INFO
#define BURST_SIZE 32
#define NUM_MBUFS 8192
#define MAX_PORTS 16

static struct rte_eth_conf port_conf = {
    .rxmode = {
        .max_rx_pkt_len = RTE_ETHER_MAX_JUMBO_LEN,
        .rte_rx_mode = RTE_ETH_RX_MODE_STRICT,
        .hwts = 0,
    },
    .txmode = {
        .default_tx_vlan_id = 0,
        .enable_tx_offload = 0,
        .hwts = 0,
    },
};

static uint16_t port_count;
static uint16_t port_ids[MAX_PORTS];
static rte_hash_table_t * mac_table;

struct mac_entry{
    uint8_t mac[6];
    uint16_t port_id;
};


static int mac_table_init(void) {
    struct rte_hash_parameters params = {
        .name = "MAC_TABLE",
        .entry_cnt = 1024,   // 最大MAC条目数
        .key_len = 6,       // MAC地址长度
        .hash_func = rte_hash_crc,
        .hash_param = 0,
    };

    mac_table = rte_hash_create(&params);
    if (!mac_table) {
        rte_panic("Failed to create MAC table");
    }

    return 0;
}


static void mac_table_add(const uint8_t * mac, uint16_t port_id){
    struct mac_entry entry;
    memset(entry.mac, mac, sizeof(entry.mac));
    entry.port_id = port_id;
    if(rte_hash_insert(mac_table, (const void *)mac, (void *)&entry, 0) != 0){
        rte_log(RTE_LOG_ERR, RTE_LOGDEV, "MAC address %6s already exists\n", rte_ether_ntop(&entry.mac, "xx:xx:xx:xx:xx:xx"));
    }
}

static uint16_t mac_talbe_lookup(const uint8_t * mac){
    struct mac_entry * entry;
    entry = rte_hash_lookup(mac_talbe, (cosnt void *)mac);
    return entry ? entry->port_id : -1;
}

static void packet_handler(struct rte_mbuf * mbufs[], uint16_t nb_rx){
    uint16_t i;
    struct rte_ehter_header * eth;
    uint8_t src_mac[6], dst_mac[6];
    uint16_t src_port, dst_port;
    for(i = 0; i < nb_rx; i++){
        struct rte_mbuf * mbuf = mbufs[i];
        eth = rte_eth_hdr(mbuf);
        memcpy(&src_mac, eth->src_addr, 6);
        memcpy(&dst_mac, eth->dst_addr, 6);

        src_prot = rte_eth_rx_burst(port_id, 0, mbuf, 1);
        mac_table_add(src_mac, port_id);

        dst_port = mac_talbe_lookup(dst_mac);
        if (dst_port != -1 && dst_port != port_id) {
            // 转发数据包
            rte_eth_tx_burst(dst_port, 0, bufs, 1);
        } else {
            // 丢弃未知目标帧
            rte_pktmbuf_free(buf);
        }
    }
}



int main(int argc, char * argv[]){
    int ret = 0;
    if(rte_eal_init(argc, argv) < 0){
        rte_exit(EXIT_FAILURE, "---->  ");
    }

    port_count = rte_eth_dev_count_avali();
    if(port_count < 2){
        return -1;        
    }

    // 保存端口ID
    for (i = 0; i < port_count; i++) {
        port_ids[i] = i;
    }

    for(int i = 0; i < port_count; i++){
        struct rte_eth_dev_info dev_info;
        
        if(rte_eth_dev_info_get(port_ids[i], &dev_info) < 0){
            rte_panic("Port %d configuration failed", port_ids[i]);
        }
        
        rte_eth_dev_set_macaddr(port_ids[i], dev_info.mac_addr);
        if(rte_eth_dev_start(port_ids[i]) < 0){
            rte_panic("Port %d start failed", port_ids[i]);
        }
    }
    mac_table_init();

    // 设置CPU亲和性
    RTE_CPU_LMASK = (1ULL << rte_eal_get_master_lcore()) - 1;

    // 主循环
    while (1) {
        struct rte_mbuf *bufs[BURST_SIZE];
        uint16_t nb_rx;

        // 接收数据包
        nb_rx = rte_eth_rx_burst(port_id, 0, bufs, BURST_SIZE);
        if (nb_rx > 0) {
            packet_handler(bufs, nb_rx);
        }
    }

    return 0;
}